package genetics;

import java.util.ArrayList;

/**
 * GeneStructure class.
 * @author pcdejager
 *
 */
public class GeneStructure {
    /**
     * Gene type enumeration.
     * @author pcdejager
     *
     */
    public enum GeneType {
        /**
         * Bit gene.
         */
        BIT,
        /**
         * Enumeration gene.
         */
        ENUM,
        /**
         * Integer gene.
         */
        INTEGER
    }

    /**
     * Entry class containing info for each gene in gene string.
     * @author pcdejager
     *
     */
    private class Entry {
        /**
         * Constructor.
         * @param startPos The start position of the gene
         * @param totalSize The size of the gene
         * @param theType The gene type
         */
        public Entry(final int startPos, final int totalSize,
                final GeneType theType) {
            start = startPos;
            size = totalSize;
            type = theType;
        }

        /**
         * The start position.
         */
        private int start;
        /**
         * The size.
         */
        private int size;
        /**
         * The type.
         */
        private GeneType type;
    }

    /**
     * Constructor.
     * @param totalSize The size of the structure
     */
    public GeneStructure(final int totalSize) {
        if (totalSize > 0) {
            size = totalSize;
        }
    }

    /**
     * Add entry to structure.
     * @param totalSize The size
     * @param type The type
     * @return True if successful else false
     */
    public final boolean addEntry(final int totalSize, final GeneType type) {
        if (isValid) {
            return false;
        }
        if (totalSize <= 0) {
            return false;
        }
        if ((type == GeneType.BIT) && (totalSize != 1)) {
            return false;
        }
        if (structure == null) {
            if (totalSize > size) {
                return false;
            }
            structure = new ArrayList<Entry>();
            structure.add(new Entry(0, totalSize, type));
        } else {
            Entry last = structure.get(structure.size() - 1);
            int start = last.start + last.size;
            if ((start + totalSize) > size) {
                return false;
            }
            structure.add(new Entry(last.start + last.size, totalSize, type));
        }
        return true;
    }

    /**
     * Finish the structure off.
     * @return True if successful, else false
     */
    public final boolean done() {
        if (structure == null) {
            return false;
        }
        if (isValid) {
            return true;
        }
        Entry last = structure.get(structure.size() - 1);
        if ((last.start + last.size) != size) {
            return false;
        }
        isValid = true;
        return true;
    }

    /**
     * Is the structure valid.
     * @return True if value else false
     */
    public final boolean isValid() {
        return isValid;
    }

    /**
     * The size.
     */
    private int size = 0;

    /**
     * Structure definition.
     */
    private ArrayList<Entry> structure = null;

    /**
     * Is the structure valid.
     */
    private boolean isValid = false;
}
